package Presenter;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
import java.sql.SQLException;

import javax.swing.JOptionPane;
import javax.swing.JPanel;

import Model.Game;
import Model.Player;
import View.MapScreen;

import javax.swing.JLabel;

import java.awt.Font;
import java.awt.FlowLayout;
import java.awt.GridLayout;

/**
 * This class is an extension of JPanel. When called, it presents the map
 * screen, i.e. WELCOME TO MULE
 * 
 * @author Matt Miller
 * 
 */

public class MainGameScreen extends JPanel implements KeyListener {

	private static final long serialVersionUID = 1L;
	private int xcord;
	private int ycord;
	private final CardLayout gameplayScreens;
	private IncrementableInteger counter;
	private final Game g;
	private int roundNum;
	private Player[] players;
	private int playerCount;
	private MapScreen map;
	private Round round;
	private TownPresenter townPresenter;
	private JPanel centerScreens;
	private JPanel infoPanel;
	private JLabel timeLabel;
	private JLabel playerLabel;
	private JLabel moneyLabel;

	// 0 in counter means displaying the map screen

	/**
	 * Sets up the main game screens with a cardlayout
	 * 
	 * @param Game
	 *            g
	 * @throws IOException 
	 */
	public MainGameScreen(Game g) throws IOException {
		this.g = g;
		round = new Round(g, this);

		centerScreens = new JPanel();
		infoPanel = new JPanel();
		
		this.setLayout(new BorderLayout());
		//this.add(infoPanel, BorderLayout.NORTH);
		infoPanel.setLayout(new GridLayout(0, 3, 0, 0));
		infoPanel.setSize(1200,30);
		
		playerLabel = new JLabel("Player Name: ");
		playerLabel.setFont(new Font("Helvetica", Font.BOLD, 14));
		infoPanel.add(playerLabel);
		
		moneyLabel = new JLabel("Money: ");
		moneyLabel.setFont(new Font("Helvetica", Font.BOLD, 14));
		infoPanel.add(moneyLabel);
		
		timeLabel = new JLabel("Remaining Time: ");
		timeLabel.setFont(new Font("Helvetica", Font.BOLD, 14));
		infoPanel.add(timeLabel);
		//this.add(centerScreens, BorderLayout.CENTER);
		
		gameplayScreens = new CardLayout();
		this.setLayout(gameplayScreens);

		map = new MapScreen(g);
		this.add(map, "Map");
		gameplayScreens.addLayoutComponent(map, "Map");

		MapScreen buffer = new MapScreen(g);
		centerScreens.add(buffer, "Buffer");
		gameplayScreens.addLayoutComponent(buffer, "Buffer");

		TownPresenter townPresenter = new TownPresenter(g, gameplayScreens, this);

		counter = new IncrementableInteger(0);
		gameplayScreens.show(this, "map");
		xcord = 0;
		ycord = 0;
		setPreferredSize(new Dimension(1200, 800));
		setVisible(true);
		setFocusable(true);
		requestFocusInWindow();
		setFocusTraversalKeysEnabled(false);
		addKeyListener(this);

		roundNum = 1;

		players = this.g.getPlayers();
		repaint();
	}

	/**
	 * Paints a square around the current square
	 * 
	 * @param Graphics
	 *            g
	 */
	@Override
	public void paint(Graphics g) {
		super.paint(g);
		if (counter.getInt() == 0) {
			g.setColor(Color.BLACK);
			g.fillRect(130 * xcord, 150 * ycord + ycord, 130, 3);
			g.fillRect(130 * xcord, 150 * ycord + ycord, 3, 160);
			g.fillRect(130 * xcord + 127, 150 * ycord + ycord, 3, 160);
			g.fillRect(130 * xcord, 150 * ycord + 157 + ycord, 130, 3);
		}
	}

	/**
	 * KeyTyped method
	 * 
	 * @param KeyEvent
	 *            e
	 */
	@Override
	public void keyTyped(KeyEvent e) {
		if (e.getKeyCode() == KeyEvent.VK_LEFT) {
			xcord = (xcord + 9 - 1) % 9;
			repaint();
		}

		else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
			xcord = (xcord + 9 + 1) % 9;
			repaint();
		}

		else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
			ycord = (ycord + 5 + 1) % 5;
			repaint();
		} else if (e.getKeyCode() == KeyEvent.VK_UP) {
			ycord = (ycord + 5 - 1) % 5;
			repaint();
		} else if (e.getKeyCode() == KeyEvent.VK_ENTER && xcord == 4
				&& ycord == 2 && counter.getInt() == 0) {
			counter.add(1);
			gameplayScreens.show(centerScreens, "TownView");
		}

		else if (e.getKeyCode() == KeyEvent.VK_ENTER && counter.getInt() == 0) {
			round.getTurn().buyTile();
			gameplayScreens.removeLayoutComponent(map);
			MapScreen newMap;
			try {
				newMap = new MapScreen(g);
				centerScreens.add(newMap);
				gameplayScreens.addLayoutComponent(newMap, "Map");
				gameplayScreens.show(centerScreens, "Map");
				repaint();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			
		}
	}

	/**
	 * Moves the cursor according to arrow keys
	 * 
	 * @param KeyEvent
	 *            e
	 */
	@Override
	public void keyPressed(KeyEvent e) {

		if (e.getKeyCode() == KeyEvent.VK_LEFT) {
			xcord = (xcord + 9 - 1) % 9;
			repaint();
		} else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
			xcord = (xcord + 9 + 1) % 9;
			repaint();
		} else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
			ycord = (ycord + 5 + 1) % 5;
			repaint();
		} else if (e.getKeyCode() == KeyEvent.VK_UP) {
			ycord = (ycord + 5 - 1) % 5;
			repaint();
		} else if (e.getKeyCode() == KeyEvent.VK_ENTER && xcord == 4
				&& ycord == 2 && counter.getInt() == 0) {
			counter.add(1);
			gameplayScreens.show(this, "TownView");
		} else if (e.getKeyCode() == KeyEvent.VK_ENTER && counter.getInt() == 0) {
			round.getTurn().buyTile();
			gameplayScreens.removeLayoutComponent(map);
			MapScreen newMap;
			try {
				newMap = new MapScreen(g);
				this.add(newMap, "Map");
				gameplayScreens.addLayoutComponent(newMap, "Map");
				gameplayScreens.show(this, "Map");
				repaint();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			
		} else if(e.getKeyCode() == KeyEvent.VK_S){
			String name = JOptionPane.showInputDialog(this, "Please enter the name of your save file");
			try {
				DatabaseTransactions.saveGame(g,round,name);
			} catch (SQLException e1) {
				System.out.println("Please enter a unique name");
			}
		}

	}

	/**
	 * KeyReleased method
	 * 
	 * @param KeyEvent
	 *            e
	 */
	@Override
	public void keyReleased(KeyEvent e) {

	}

	/**
	 * Returns the counter
	 * 
	 * @return IncrementableInteger counter
	 */
	public IncrementableInteger getCounter() {
		return counter;
	}

	/**
	 * Returns the cardlayout manager
	 * 
	 * @return CardLayout cardlayout
	 */
	public CardLayout getLayoutManager() {
		return (CardLayout) this.getLayout();
	}

	/**
	 * Increments the player counter
	 */
	public void incrementPlayerCounter() {
		playerCount = (playerCount + 1 + 4) % 4;
	}

	/**
	 * Increments the round counter
	 */
	public void incrementRound() {
		if (playerCount == 3) {
			roundNum = roundNum + 1;
		}
	}

	/**
	 * Getter for current x-coordinate
	 * 
	 * @return
	 */
	public int getXCord() {
		return xcord;
	}

	/**
	 * Getter for current y-coordinate
	 * 
	 * @return
	 */
	public int getYCord() {
		return ycord;
	}

	/**
	 * Getter for round
	 * 
	 * @return
	 */
	public Round getRound() {
		return round;
	}

	/**
	 * setter for townPresenter
	 * 
	 * @param tp
	 */
	public void refreshTownPresenter() {
		townPresenter = new TownPresenter(g, gameplayScreens, this);
	}
	
	/**
	 * Updates the time label in the info panel
	 * @param newTime
	 */
	public void updateTime(int newTime)
	{
		timeLabel.setText("Remaining Time: "+newTime);
	}
	
	/**
	 * Updates the player name label in the info panel
	 * @param playerName
	 */
	public void updatePlayer(String playerName)
	{
		playerLabel.setText("Player Name: "+playerName);
	}
	
	/**
	 * Updates the money label in the info panel
	 * @param currentMoney
	 */
	public void updateMoney(int currentMoney)
	{
		moneyLabel.setText("Money: "+currentMoney);
	}
	
	/**
	 * Returns the centerScreen panel that contains the main game play.
	 * @return
	 */
	public JPanel getCenterScreen()
	{
		return centerScreens;
	}
	

}